package cn.rkylin.oms.salespromotion.rules.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;

import cn.rkylin.core.service.ApolloService;
import cn.rkylin.oms.order.vo.OrderVO;
import cn.rkylin.oms.salespromotion.rules.dao.ISalesPromotionConstrainGoodsDAO;
import cn.rkylin.oms.salespromotion.rules.dao.ISalesPromotionGiftDAO;
import cn.rkylin.oms.salespromotion.rules.dao.ISalesPromotionRuleDAO;
import cn.rkylin.oms.salespromotion.rules.dao.ISalesPromotionShopDAO;
import cn.rkylin.oms.salespromotion.rules.domain.SalesPromotionConstrainGoods;
import cn.rkylin.oms.salespromotion.rules.domain.SalesPromotionGift;
import cn.rkylin.oms.salespromotion.rules.domain.SalesPromotionRule;
import cn.rkylin.oms.salespromotion.rules.domain.SalesPromotionShop;
import cn.rkylin.oms.salespromotion.rules.service.ISalesPromotionRuleService;
import cn.rkylin.oms.salespromotion.rules.util.GiftCaculatorUtil;
import cn.rkylin.oms.salespromotion.rules.util.handler.RuleMatchHandler;
import cn.rkylin.oms.salespromotion.rules.util.stretegy.IGiftCaculateStretegy;
import cn.rkylin.oms.salespromotion.rules.vo.SalesPromotionRuleVO;

@Service("salesPromotionRuleService")
public class SalesPromotionRuleServiceImpl extends ApolloService implements ISalesPromotionRuleService {
    /**
     * 促销规则相关数据访问对象
     */
    @Autowired
    private ISalesPromotionRuleDAO ruleDAO;
    /**
     * 促销规则相关数据访问对象
     */
    @Autowired
    private ISalesPromotionGiftDAO giftDAO;
    /**
     * 促销规则相关数据访问对象
     */
    @Autowired
    private ISalesPromotionConstrainGoodsDAO constrainGoodsDAO;
    /**
     * 促销规则相关数据访问对象
     */
    @Autowired
    private ISalesPromotionShopDAO ruleShopDAO;

    @Override
    public PageInfo<SalesPromotionRuleVO> findRuleList(int page, int rows, SalesPromotionRuleVO ruleVO) throws Exception {
        PageInfo<SalesPromotionRuleVO> ruleVOList = findPage(page, rows, "pageSelectSalesPromotionRule", ruleVO);
        // 设置每条规则相关的店铺列表
        for (SalesPromotionRuleVO salesPromotionRuleVO : ruleVOList.getList()) {
            List<SalesPromotionShop> shopList = ruleShopDAO.selectByRuleId(salesPromotionRuleVO.getRuleId());
            salesPromotionRuleVO.setShopList(shopList);

            //  此处需要再调用一次setEnvolvingShops，因为这时候shoplist中才有了值
            salesPromotionRuleVO.setEnvolvingShops(StringUtils.EMPTY);
        }
        return ruleVOList;
    }

    @Override
    @Transactional
    public int enableRuleState(String ruleId) {
        int returnValue = 0;
        SalesPromotionRule rule = new SalesPromotionRule();
        String[] ruleIdArray = StringUtils.split(ruleId, ",");
        Date now = new Date();
        try {
            for (String ruleid : ruleIdArray) {
                rule.setRuleId(ruleid);
                rule.setIsEnable(SalesPromotionRule.RULE_STATE_ENABLE);
                rule.setUpdateTime(now);
                returnValue = ruleDAO.updateSalesPromotionRule(rule);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnValue;
    }

    @Override
    @Transactional
    public int disableRuleState(String ruleId) {
        int returnValue = 0;
        SalesPromotionRule rule = new SalesPromotionRule();
        String[] ruleIdArray = StringUtils.split(ruleId, ",");
        Date now = new Date();
        try {
            for (String ruleid : ruleIdArray) {
                rule.setRuleId(ruleid);
                rule.setIsEnable(SalesPromotionRule.RULE_STATE_DISABLE);
                rule.setUpdateTime(now);
                returnValue = ruleDAO.updateSalesPromotionRule(rule);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnValue;
    }

    /*
     * * 本实现强制设置： 创建时间-当前时间 更新时间-当前时间 删除状态-N IDRangeConstrainEnable = N IDRange
     * - ""
     * 
     * @see
     * cn.rkylin.oms.salespromotion.rules.service.ISalesPromotionRuleService#
     * insertRule(cn.rkylin.oms.salespromotion.rules.vo.SalesPromotionRuleVO)
     */
    @Override
    @Transactional
    public SalesPromotionRuleVO insertRule(SalesPromotionRuleVO ruleVO) {
        SalesPromotionRule rule = new SalesPromotionRule();
        Date now = new Date();
        try {
            BeanUtils.copyProperties(ruleVO,rule);

            if (StringUtils.isEmpty(rule.getRuleId())) {
                ruleVO.setRuleId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
            }

            rule.setIsIdRangeConstrainEnable(SalesPromotionRuleVO.VALUE_NO);
            rule.setIdRange(StringUtils.EMPTY);

            rule.setCreateTime(now);
            rule.setUpdateTime(now);

            rule.setDeleted(SalesPromotionRuleVO.VALUE_NO);

            ruleDAO.insertSalesPromotionRule(rule);
            // 插入规则相关的店铺列表
            for (SalesPromotionShop shop : ruleVO.getShopList()) {
                shop.setRelRuleId(rule.getRuleId());
                shop.setShopRuleId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                shop.setCreateTime(now);
                shop.setUpdateTime(now);
                shop.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                ruleShopDAO.insert(shop);
            }

            // 插入规则相关的赠品列表
            for (SalesPromotionGift gift : ruleVO.getGiftList()) {
                gift.setPresentId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                gift.setRelRuleId(rule.getRuleId());
                gift.setCreateTime(now);
                gift.setUpdateTime(now);
                gift.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                giftDAO.insert(gift);
            }

            // 如果计算限制商品，插入规则相关的限制商品列表
            if ("y".equals(ruleVO.getIsConstrainGoodsEnable())) {
                for (SalesPromotionConstrainGoods constrainGoods : ruleVO.getConstrainGoodsList()) {
                    constrainGoods.setConstrainGoodsId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                    constrainGoods.setCreateTime(now);
                    constrainGoods.setUpdateTime(now);
                    constrainGoods.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                    constrainGoods.setRelRuleId(rule.getRuleId());
                    constrainGoodsDAO.insert(constrainGoods);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ruleVO;
    }

    @Override
    @Transactional
    public SalesPromotionRuleVO updateRule(SalesPromotionRuleVO ruleVO) {
        SalesPromotionRule rule = new SalesPromotionRule();
        Date now = new Date();
        try {
            BeanUtils.copyProperties(ruleVO,rule);
            rule.setUpdateTime(new Date());
            ruleDAO.updateSalesPromotionRule(rule);

            if (SalesPromotionRuleVO.VALUE_YES.equals(ruleVO.getGiftEditFlag())) {
                // 先删除旧的赠品，再添加新的赠品
                giftDAO.deleteByRuleId(ruleVO.getRuleId());
                for (SalesPromotionGift gift : ruleVO.getGiftList()) {
                    gift.setPresentId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                    gift.setRelRuleId(rule.getRuleId());
                    gift.setCreateTime(now);
                    gift.setUpdateTime(now);
                    gift.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                    giftDAO.insert(gift);
                }
            }

            if (SalesPromotionRuleVO.VALUE_YES.equals(ruleVO.getShopEditFlag())) {
                // 先删除旧的店铺，再添加新的店铺
                ruleShopDAO.deleteByRuleId(ruleVO.getRuleId());
                for (SalesPromotionShop shop : ruleVO.getShopList()) {
                    shop.setRelRuleId(rule.getRuleId());
                    shop.setShopRuleId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                    shop.setCreateTime(now);
                    shop.setUpdateTime(now);
                    shop.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                    ruleShopDAO.insert(shop);
                }
            }

            if (SalesPromotionRuleVO.VALUE_YES.equals(ruleVO.getConstrainGoodsEditFlag())) {
                // 删除旧的限制商品
                constrainGoodsDAO.deleteByRuleId(ruleVO.getRuleId());
                if (SalesPromotionRuleVO.VALUE_YES.equals(ruleVO.getIsConstrainGoodsEnable())) {
                    for (SalesPromotionConstrainGoods constrainGoods : ruleVO.getConstrainGoodsList()) {
                        constrainGoods.setConstrainGoodsId(java.util.UUID.randomUUID().toString().replaceAll("-", ""));
                        constrainGoods.setCreateTime(now);
                        constrainGoods.setUpdateTime(now);
                        constrainGoods.setDeleted(SalesPromotionRuleVO.VALUE_NO);
                        constrainGoods.setRelRuleId(rule.getRuleId());
                        constrainGoodsDAO.insert(constrainGoods);
                    }
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return ruleVO;
    }

    @Override
    @Transactional
    public SalesPromotionRuleVO insertRuleByOriginRuleId(String originRuleId) {
        // 根据ruleID获取rule的详细内容
        SalesPromotionRuleVO ruleObj = findRuleById(originRuleId);

        // 变更ruleobj的ruleID，并在名称上添加“_复制”字样，表示这是复制出的规则。
        String strUuid = java.util.UUID.randomUUID().toString().replaceAll("-", "");
        ruleObj.setRuleId(strUuid);
        ruleObj.setRuleName(ruleObj.getRuleName() + "_复制");

        // 新增规则
        insertRule(ruleObj);
        return ruleObj;
    }

    @Override
    @Transactional
    public int deleteRule(String ruleId) {
        // 传入的参数是逗号分隔的ruleId字符串，执行批量删除
        int returnValue = 0;
        try {
            String[] ruleIdArray = StringUtils.split(ruleId, ",");
            for (String ruleid : ruleIdArray) {
                returnValue = ruleDAO.deleteSalesPromotionRuleById(ruleid);
                returnValue = ruleShopDAO.deleteByRuleId(ruleid);
                returnValue = giftDAO.deleteByRuleId(ruleid);
                returnValue = constrainGoodsDAO.deleteByRuleId(ruleid);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnValue;
    }

    @Override
    public SalesPromotionRuleVO findRuleById(String ruleId) {
        SalesPromotionRuleVO ruleVO = new SalesPromotionRuleVO();
        SalesPromotionRuleVO param = new SalesPromotionRuleVO();
        param.setRuleId(ruleId);
        try {
            PageInfo<SalesPromotionRuleVO> ruleVOList = findPage(1, 1, "pageSelectSalesPromotionRule", param);
            if (ruleVOList.getList().size() > 0) {
                ruleVO = ruleVOList.getList().get(0);
                // 获取规则相关店铺列表
                List<SalesPromotionShop> shopList = ruleShopDAO.selectByRuleId(ruleId);
                ruleVO.setShopList(shopList);
                // 获取规则相关赠品列表
                List<SalesPromotionGift> giftList = giftDAO.selectByRuleId(ruleId);
                ruleVO.setGiftList(giftList);
                // 如果限制商品开关为true，则获取限制商品列表
                if ("y".equalsIgnoreCase(ruleVO.getIsConstrainGoodsEnable())) {
                    // 获取规则相关限制商品列表
                    List<SalesPromotionConstrainGoods> constrainGoodsList = constrainGoodsDAO.selectByRuleId(ruleId);
                    ruleVO.setConstrainGoodsList(constrainGoodsList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ruleVO;
    }

    /**
     * 根据系统订单计算赠品列表.
     * 
     * @throws Exception
     * @see cn.rkylin.oms.salespromotion.rules.service.ISalesPromotionRuleService#generateGiftList(cn.rkylin.oms.order.vo.OrderVO)
     */
    @Override
    public Map<String, Object> generateGiftList(OrderVO order) throws Exception {
        Map<String, Object> giftMap = new HashMap<String, Object>();

        // 获取可用规则列表
        List<SalesPromotionRuleVO> ruleVOList = getRuleVOList4Caculate(order);

        RuleMatchHandler ruleMatchHandler = GiftCaculatorUtil.getRuleMatchHandlr(); // 规则校验器
        for (SalesPromotionRuleVO salesPromotionRuleVO : ruleVOList) {
            Map<String, String> result = ruleMatchHandler.HandleRequest(order, salesPromotionRuleVO);
            if (!RuleMatchHandler.SUCCESS.equals(result.get(RuleMatchHandler.RESULT))) {
                // 如果校验不通过，则不计算；
                giftMap.put(salesPromotionRuleVO.getRuleId(), result.get(RuleMatchHandler.RESULT));
            } else {
                List<Map<String, Object>> giftList = new ArrayList<Map<String, Object>>();
                // 如果校验通过就计算赠品列表
                IGiftCaculateStretegy stretegy = GiftCaculatorUtil.getCaculateStretegy(salesPromotionRuleVO); // 规则计算
                if (null != stretegy) {
                    giftList = stretegy.getGifts(salesPromotionRuleVO, order);
                }
                giftMap.put(salesPromotionRuleVO.getRuleId(), giftList);
            }
        }
        return giftMap;
    }

    /**
     * getRuleVOList4Caculate:根据订单内容获取可用的规则列表. <br/>
     *
     * @author zhanghao
     * @param queryParam
     * @return
     * @throws Exception
     */
    private List<SalesPromotionRuleVO> getRuleVOList4Caculate(OrderVO order) throws Exception {
        SalesPromotionRuleVO queryParam = new SalesPromotionRuleVO();

        /*
         * 查询符合下述条件的规则 <br/> 1. 启用状态的规则 <br/> 2.1. 拍单时间，且拍单时间介于规则时间内<br/> 2.2.
         * 付款时间，且付款时间介于规则时间内<br/>  3. 店铺符合要求
         */

        queryParam.setPayTime(order.getPaidDate());
        queryParam.setOrderTime(order.getOrderTime());
        queryParam.setShopId(order.getShopId());
        queryParam.setOrderAmount(order.getPaidFee());

        List<SalesPromotionRuleVO> ruleVOList = ruleDAO.selectAvailableRule(queryParam);

        return ruleVOList;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public List<HashMap> findStateCount(SalesPromotionRuleVO queryParamVO) throws Exception {
        List<HashMap> returnMap = ruleDAO.selectStateCount(queryParamVO);
        return returnMap;
    }
    
    /**
     * true - 不重复，校验通过；false - 重复，校验不通过.
     * @see cn.rkylin.oms.salespromotion.rules.service.ISalesPromotionRuleService#duplicatedValid(cn.rkylin.oms.salespromotion.rules.vo.SalesPromotionRuleVO)
     */
    @Override
    public boolean duplicatedValid(SalesPromotionRuleVO ruleVO) throws Exception {
        boolean returnResult = true;
        List<SalesPromotionRuleVO> ruleVOList = ruleDAO.selectDuplicatedRule(ruleVO);
        if(ruleVOList.size()==0) {
            returnResult = true;
        }else {
            boolean isRuleSame = false;
            for (SalesPromotionRuleVO salesPromotionRuleVO : ruleVOList) {
                isRuleSame = isRuleSame(ruleVO,salesPromotionRuleVO);
                if(isRuleSame) {
                    returnResult = false;
                    break;
                }
            }
        }
        return returnResult;
    }

    /**
     * validIsRuleSame:比较两个规则是否相同. <br/>
     *
     * @author zhanghao
     * @param ruleVO
     * @param salesPromotionRuleVO
     */
    private boolean isRuleSame(SalesPromotionRuleVO origin, SalesPromotionRuleVO compare) {
        boolean isRuleSame = false;
        JSONObject originRule = JSON.parseObject(origin.getPresentCaculateRule());
        JSONObject compareRule = JSON.parseObject(compare.getPresentCaculateRule());
        
        if(originRule.getString("sendType").equals(compareRule.getString("sendType"))) {
            isRuleSame = true;
        }
        
        return isRuleSame;
    }
}
